/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Download Sort.
 *
 * The Initial Developer of the Original Code is
 * Devon Jensen.
 *
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s): Devon Jensen <velcrospud@hotmail.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */


// old functions
//var __foundHeaderInfo = window.foundHeaderInfo;
var ORIG_getTargetFile = window.getTargetFile;
//var __contentAreaClick = window.contentAreaClick;

window.addEventListener("load", downsortinit, true);
//window.addEventListener("unload", downsortclose, false);
var ds_datasource;
//var ds_sink;
//var ds_remote;
var ds_loaded;

var ds_RDFC = '@mozilla.org/rdf/container;1';
ds_RDFC = Components.classes[ds_RDFC].createInstance();
ds_RDFC = ds_RDFC.QueryInterface(Components.interfaces.nsIRDFContainer);

var ds_RDFCUtils = '@mozilla.org/rdf/container-utils;1';
ds_RDFCUtils = Components.classes[ds_RDFCUtils].getService();
ds_RDFCUtils = ds_RDFCUtils.QueryInterface(Components.interfaces.nsIRDFContainerUtils);

var ds_RDF = '@mozilla.org/rdf/rdf-service;1';
ds_RDF = Components.classes[ds_RDF].getService();
ds_RDF = ds_RDF.QueryInterface(Components.interfaces.nsIRDFService);


function downsortinit() {
	
	if (!ds_loaded) {
		ds_loaded = true;
	  	//window.removeEventListener("load", downsortinit, true);
	  	// Set replacement functions
	  	//window.foundHeaderInfo = ds_foundHeaderInfo;
	  	window.getTargetFile = ds_getTargetFile;
	  	//window.contentAreaClick = ds_contentAreaClick;
	  	
		//toJavaScriptConsole();
		//BrowserOpenExtensions('extensions');

		var gIOService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
		// From TBE
		const DIR = Components.classes['@mozilla.org/file/directory_service;1'].getService(Components.interfaces.nsIProperties);
		var dir = DIR.get('ProfD', Components.interfaces.nsILocalFile);

		var tempLocalFile = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
		tempLocalFile.initWithPath(dir.path);

		var uri;
		try {
			uri = gIOService.newFileURI(tempLocalFile).spec;
		}
		catch(e) {}

		if (!uri.match(/\/$/)) uri += '/';
		// /from TBE

		ds_datasource = ds_RDF.GetDataSourceBlocking(uri + "downsort.rdf");
		
		// Make sure the rootnodes are there and set up, on error, they are created
		var extRootNode = ds_RDF.GetResource("NC:ExtensionRoot");
		var keyRootNode = ds_RDF.GetResource("NC:KeywordRoot");
		var defRootNode = ds_RDF.GetResource("NC:DefaultRoot");
		try {
	      ds_RDFC.Init(ds_datasource,extRootNode);
	    } catch (e) {
	      ds_RDFCUtils.MakeSeq(ds_datasource,extRootNode);
	      ds_RDFC.Init(ds_datasource,extRootNode);
	    }
	    try {  
	    	ds_RDFC.Init(ds_datasource,keyRootNode);
	    } catch (e) {
	    	ds_RDFCUtils.MakeSeq(ds_datasource,keyRootNode);
	    	ds_RDFC.Init(ds_datasource,keyRootNode);
	    }
	    try {
	    	ds_RDFC.Init(ds_datasource,defRootNode);
	    } catch (e) { // Set up the default settings
	    	ds_resetDefaults();
	    }
	    
		//ds_remote = ds_datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
		
		// Need to set this timeout to 0 or else the savelinkas wont use my codepath
			// this means that the filename won't always be correct
			// - see saveLink in nsContextMenu.js
		var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
		prefs.setIntPref("browser.download.saveLinkAsFilenameTimeout", 0);
		
		var obsSvc = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
		obsSvc.addObserver(ds_quitObserver, "quit-application-requested", false);
	}
	
}

var ds_quitObserver = {
	observe: function(subject, topic, state) {
	
		//alert(topic);
		if(topic == "quit-application-requested") {
			var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
			prefs.setIntPref("browser.download.saveLinkAsFilenameTimeout", 1000);
			
		}
	}
};


function downsortclose() {

}

//function ds_getTargetFile(aData, aSniffer, aContentType, aIsDocument, aSkipPrompt, aSaveAsTypeResult) {
function ds_getTargetFile(aFpP, aSkipPrompt) {	

	remoteURL = aFpP.fileInfo.uri.spec;
	defaultExtension = aFpP.fileInfo.fileExt;
	defaultExtension = defaultExtension.toLowerCase();
    defaultString = getNormalizedLeafName(aFpP.fileInfo.fileName, aFpP.fileInfo.fileExt);
                                             
	var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
	var promptSkip = false;
	
	//d("defFileName " + defaultFileName);
	//d("defExt " + defaultExtension);
	//d("defString " + defaultString);
	
// Check if we have a listing
	var foundKeyword = ds_checkForKeyword(remoteURL); // Returns the found keyword, or -1 if none found
	if (foundKeyword != -1)// Found a keyword match
		var aSource = ds_RDF.GetResource("NC:KeywordRoot:" + foundKeyword);
		
	else { // Look for extension match
		var foundExt = ds_checkForExtension(defaultExtension); // Returns -1 if not found
		if (foundExt != -1)
			var aSource = ds_RDF.GetResource("NC:ExtensionRoot:" + defaultExtension);
		/*
		else // No match for either keyword or extension, use default settings
			var aSource = ds_RDF.GetResource("NC:DefaultRoot:default");
		*/
	}
	
	//d(foundKeyword + " : " + foundExt);
	
	// If we don't have any rules to match the download, send it to the firefox's built-in function
	if (!aSource) {
		return ORIG_getTargetFile(aFpP, aSkipPrompt);
	}
	
// Get the info from keyword, extension, or default (if we didn't have a listing)
	try {
		var savRDF = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#saving");
		var autoSaving = ds_datasource.GetTarget(aSource, savRDF, true);
		autoSaving = autoSaving.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
		
		var subfRDF = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#subfolder");
		var autoSubf = ds_datasource.GetTarget(aSource, subfRDF, true);
		autoSubf = autoSubf.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
		
		var locRDF = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#location");
		var autoLocation = ds_datasource.GetTarget(aSource, locRDF, true);
		autoLocation = autoLocation.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
		
		var actionRDF = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#action");
		var autoAction = ds_datasource.GetTarget(aSource, actionRDF, true);
		autoAction = autoAction.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
		
	} catch(e) { // If we fail to get a value for any of these, try again with the defaults
		if(foundKeyword == -1 && foundExt == -1) { // We were using the defaults, they must be bad
			ds_resetDefaults();
		}
		else
			var aSource = ds_RDF.GetResource("NC:DefaultRoot:default");
			
		var autoSaving = ds_datasource.GetTarget(aSource, savRDF, true);
		autoSaving = autoSaving.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
		var autoSubf = ds_datasource.GetTarget(aSource, subfRDF, true);
		autoSubf = autoSubf.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
		var autoLocation = ds_datasource.GetTarget(aSource, locRDF, true);
		autoLocation = autoLocation.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
		var autoAction = ds_datasource.GetTarget(aSource, actionRDF, true);
		autoAction = autoAction.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
	}
	
	//d("autosaving: " + autoSaving);
	//d("location: " + autoLocation);
	//d("action: " + autoAction);
	//d("subf: " + autoSubf);
	
// dir is what will be returned at the end - start out in the saved location
	const nsILocalFile = Components.interfaces.nsILocalFile;
	const lfContractID = "@mozilla.org/file/local;1";	
	var dir = Components.classes[lfContractID].createInstance(nsILocalFile);	
	dir.initWithPath(autoLocation);
	
// Automatic saving	
	if(autoSaving == "selectAuto") {
		
		promptSkip = true;
		
	// Add a subfolder if necessary
		if (autoSubf != "selectNone") {
			var subaddon;
			if (autoSubf == "selectDate") {
				try {
					var USdate = prefs.getIntPref("downsort.dateform.us");
				} catch (e) {}
				var date = new Date();
				var da  = date.getDate();
				var day = (da < 10) ? '0' + da : da;
				var m = date.getMonth() + 1;
				var month = (m < 10) ? '0' + m : m;
				var yy = date.getYear();
				var year = (yy < 1000) ? yy + 1900 : yy;
				if (USdate == 0)
					subaddon = month + "." + day + "." + year;
				else if (USdate == 1)
					subaddon = year + "." + month + "." + day;
				else 
					subaddon = day + "." + month + "." + year;
					
			}
			else if (autoSubf == "selectSite") {
				subaddon = aFpP.fileInfo.uri.host;
			}
			else if (autoSubf == "selectRefDom") {
				var currUrl = self._content.location.href;
				subaddon = currUrl.split("/")[2];
			}
			else if (autoSubf == "selectSubExt") {
				subaddon = defaultExtension;
			}
			else if (autoSubf == "selectHier") {
				subaddon = aFpP.fileInfo.uri.host;
				
				// This is how contextareautils does it - either is prob okay
				//navigator.appVersion.indexOf("Windows") != -1
				if (autoLocation.charAt(0) == "/")  // Linux filesystem
					subaddon = subaddon + aFpP.fileInfo.uri.directory;
				else								 // Windows
					subaddon = subaddon + aFpP.fileInfo.uri.directory.replace(/\//g,"\\");
				
				subaddon = subaddon.substring(0, subaddon.length-1);
			}
			
			dir.appendRelativePath(subaddon);
		}
		
		// This is the directory we will be saving in - Create it in case it's a new folder and/or subfolder
		try {
			dir.create(1, 0777);
		} catch (e) {}
		
		//Make a test directory to try out the default filename
		var testdir = Components.classes[lfContractID].createInstance(nsILocalFile);
		testdir.initWithPath(dir.path);
		testdir.append(defaultString);

	// Check if the file already exists, if it does do what is required	(prompt,increment, cancel, or overwrite)
		if (testdir.exists()) {
			//d("alreadyexists");
  	  		if (autoAction == "selectCanc") {
  	  			
  	  			try {
  	  				var soundpref = prefs.getBoolPref("downsort.cancel.sound");
  	  				var showpref = prefs.getBoolPref("downsort.cancel.show");
  	  			}
  	  			catch (e) {}
  	  			
  	  			if (soundpref) {
	  	  			// Play a sound
	  	  			var kSOUNDContractID = "@mozilla.org/sound;1";
	  				var kSOUNDIID = Components.interfaces.nsISound;
	  				var sound = Components.classes[kSOUNDContractID].createInstance(kSOUNDIID);
	  				sound.beep();
	  			}
	  			
	  			if (showpref) {
	  				testdir.reveal();
	  			}
  	  			//d("canceling");
  	  			return;
  	  		}
  	  		if (autoAction == "selectPrompt") {
    			promptSkip = false;
    		}
    		else { // Overwrite or ...
    			dir.append(defaultString); 
    		}
  	  		if (autoAction == "selectIncr") { // increment
    			dir.createUnique(0, 0777);
    		}
    		
    	}
    	else { // file didn't exist already
    		dir.append(defaultString);
    	}
    	
    	if(prefs.getBoolPref("downsort.function.showNote")) {
    		document.getElementById("statusbar-display").label = "Automatically saving to: " + dir.path;
    		window.setTimeout("ds_cancelStatusDisp()", 2000);
    	}
	}
	
// Prompting
	if(!promptSkip || !dir) {
		//d("inprompt");
		
		var fp = makeFilePicker();
		var titleKey = aFpP.fpTitleKey || "SaveLinkTitle";
		
		var bundle = getStringBundle();
		
		fp.init(window, bundle.GetStringFromName(titleKey), 
		        Components.interfaces.nsIFilePicker.modeSave);
		        
		var urlExt = null;
	    try {
	      var url = aSniffer.uri.QueryInterface(Components.interfaces.nsIURL);
	      urlExt = url.fileExtension;
	    }
	    catch (e) {}
		
		//appendFiltersForContentType(fp, aContentType, urlExt,
		//                            aIsDocument ? MODE_COMPLETE : MODE_FILEONLY);
		
		appendFiltersForContentType(fp, aFpP.contentType, aFpP.fileInfo.fileExt,
                                aFpP.saveMode);
		
		/*if (aIsDocument) {
      		try {
        		fp.filterIndex = prefs.getIntPref("browser.download.save_converter_index");
      		}
      		catch (e) {}
    	}*/
    	
    	if (aFpP.isDocument) {
	      try {
	        fp.filterIndex = prefs.getIntPref("browser.download.save_converter_index");
	      }
	      catch (e) {
	      }
	    }
    	
		if (dir)
		  fp.displayDirectory = dir;
		
		fp.defaultExtension = defaultExtension;
		fp.defaultString = defaultString;
		
		if (fp.show() == Components.interfaces.nsIFilePicker.returnCancel || !fp.file)
		  return false;
		/*  
		aSaveAsTypeResult.rv = fp.filterIndex;
		if (aIsDocument)
      		prefs.setIntPref("browser.download.save_converter_index", aSaveAsTypeResult.rv);
  		*/
  			
	    fp.file.leafName = validateFileName(fp.file.leafName);
	    aFpP.saveAsType = fp.filterIndex;
	    dir = fp.file;
	    aFpP.fileURL = fp.fileURL;
	
	    if (aFpP.isDocument)
	      prefs.setIntPref("browser.download.save_converter_index", aFpP.saveAsType);
	  		
		// If "prompt in last" is selected we need to save the new path
		if (autoSaving == "selectLast") {
			
			var arcFold = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#location");
			var foldLit = ds_RDF.GetLiteral(fp.file.parent.path);
			
			var targetExists = ds_datasource.GetTarget(aSource, arcFold, true);
			if(targetExists != null)
				ds_datasource.Change(aSource, arcFold, targetExists, foldLit);
		}
	}

	//d("finaldir: " + dir.path);

	aFpP.file = dir;
	return true;
}

function ds_checkForKeyword(aURL) {
	
	// Get a reference to all the keywords and go through and check each one against the url
	var keyroot = ds_RDF.GetResource("NC:KeywordRoot");
    var ds_RDFCont = Components.classes["@mozilla.org/rdf/container;1"].createInstance(Components.interfaces.nsIRDFContainer);
    ds_RDFCont.Init(ds_datasource, keyroot);
    var keygroup = ds_RDFCont.GetElements();
    var match = "0";
    var matchResult = -1; // In case there are no keywords
    var extRDF = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#ext");
    
    var prefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
    var useRegExp = prefs.getBoolPref("downsort.function.useRegExp");
    var regExp;
    
    while (keygroup.hasMoreElements()) {
    	var aKeywordRes = keygroup.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
    	aKeyword = ds_datasource.GetTarget(aKeywordRes, extRDF, true);
    	aKeyword = aKeyword.QueryInterface(Components.interfaces.nsIRDFLiteral).Value
    	if(useRegExp) {
    		var pattern = aKeyword.split("/")[1];
    		//d("pat: " + pattern);
    		var flags = aKeyword.split("/")[2];
    		//d("flags: " + flags)
    		var regExp = new RegExp (pattern, flags);
    		//d(regExp);
    		matchResult = aURL.search(regExp);  // Matching here, -1 means no match
    	}
    	else {
    		aKeyword = aKeyword.toLowerCase();
    		matchResult = aURL.toLowerCase().indexOf(aKeyword);  // Matching here, -1 means no match
    	}
		//d(aKeyword);
		//d(matchResult);
		if (matchResult != -1) {
			//d("match!");
			break;
		}
		else {
			//d("nomatch");
		}
    }
    
    if (matchResult != -1)// If we had a keyword match, use that info
		return aKeyword;
	else 
		return -1;

}

function ds_checkForExtension(ext) {
	//d("inextension" + ext);
	var extroot = ds_RDF.GetResource("NC:ExtensionRoot");
    var ds_RDFCont = Components.classes["@mozilla.org/rdf/container;1"].createInstance(Components.interfaces.nsIRDFContainer);
    ds_RDFCont.Init(ds_datasource, extroot);
    var extRes = ds_RDF.GetResource("NC:ExtensionRoot:" + ext);
    return ds_RDFCont.IndexOf(extRes);
    
}

function ds_resetDefaults() {
	
	var defRootNode = ds_RDF.GetResource("NC:DefaultRoot");
	var rootCont = ds_RDFCUtils.MakeSeq(ds_datasource,defRootNode);
	ds_RDFC.Init(ds_datasource,defRootNode);
	var defRes = ds_RDF.GetResource("NC:DefaultRoot:default");
	rootCont.AppendElement(defRes);

    var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties);
    function getDesktopKey(){      
    	return "DeskP";
    	return "Home";
    }
    var dir = fileLocator.get(getDesktopKey(), Components.interfaces.nsILocalFile);  
	
	var foldLit = ds_RDF.GetLiteral(dir.path);
	var actLit = ds_RDF.GetLiteral("selectPrompt");
	var saveLit = ds_RDF.GetLiteral("selectLast");
	var subLit = ds_RDF.GetLiteral("selectNone");
	
	var arcFold = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#location");
	var arcAct = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#action");
	var arcSave = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#saving");
	var arcSub = ds_RDF.GetResource("http://home.netscape.com/NC-rdf#subfolder");
	
	var targetExists = ds_datasource.GetTarget(defRes, arcFold, true);
	if(targetExists != null)
		ds_datasource.Change(defRes, arcFold, targetExists, foldLit);
	else
		ds_datasource.Assert(defRes, arcFold, foldLit, true);
		
	targetExists = ds_datasource.GetTarget(defRes, arcFold, true);
	if(targetExists != null)
		ds_datasource.Change(defRes, arcAct, targetExists, actLit);
	else
		ds_datasource.Assert(defRes, arcAct, actLit, true);
		
	targetExists = ds_datasource.GetTarget(defRes, arcFold, true);
	if(targetExists != null)
		ds_datasource.Change(defRes, arcSave, targetExists, saveLit);
	else
		ds_datasource.Assert(defRes, arcSave, saveLit, true);
		
	targetExists = ds_datasource.GetTarget(defRes, arcFold, true);
	if(targetExists != null)
		ds_datasource.Change(defRes, arcSub, targetExists, subLit);
	else
		ds_datasource.Assert(defRes, arcSub, subLit, true);
}

function ds_cancelStatusDisp() {
	document.getElementById("statusbar-display").label = "Done";	
}
 
 
 // Called whenever the user clicks in the content area,
 // except when left-clicking on links (special case)
 // should always return true for click to go through
 function ds_contentAreaClick(event, fieldNormalClicks) 
 {
 
   var target = event.target;
   var linkNode;

   var local_name = target.localName;

   if (local_name) {
     local_name = local_name.toLowerCase();
   }

   switch (local_name) {
     case "a":
     case "area":
     case "link":
       if (target.hasAttribute("href")) 
         linkNode = target;
       break;
     default:
       linkNode = findParentNode(event.originalTarget, "a");
       // <a> cannot be nested.  So if we find an anchor without an
       // href, there is no useful <a> around the target
       if (linkNode && !linkNode.hasAttribute("href"))
         linkNode = null;
       break;
   }
   if (linkNode) {
     if (event.button == 0 && !event.ctrlKey && !event.shiftKey &&
         !event.altKey && !event.metaKey) {
       // A Web panel's links should target the main content area.  Do this
       // if no modifier keys are down and if there's no target or the target equals
       // _main (the IE convention) or _content (the Mozilla convention).
       // The only reason we field _main and _content here is for the markLinkVisited
       // hack.
       target = linkNode.getAttribute("target");
       if (fieldNormalClicks && 
           (!target || target == "_content" || target  == "_main")) 
         // IE uses _main, SeaMonkey uses _content, we support both
       {
         if (!linkNode.href) return true;
         if (linkNode.getAttribute("onclick")) return true;
         var postData = { };
         var url = getShortcutOrURI(linkNode.href, postData);
         if (!url)
           return true;
         markLinkVisited(linkNode.href, linkNode);
         loadURI(url, null, postData.value);
         event.preventDefault();
         return false;
       }
       else if (linkNode.getAttribute("rel") == "sidebar") {
         // This is the Opera convention for a special link that - when clicked - allows
         // you to add a sidebar panel.  We support the Opera convention here.  The link's
         // title attribute contains the title that should be used for the sidebar panel.
         openDialog("chrome://browser/content/bookmarks/addBookmark2.xul", "",
                    "centerscreen,chrome,dialog,resizable,dependent",
                    linkNode.getAttribute("title"), 
                    linkNode.href, null, null, null, null, true);
         event.preventDefault();
         return false;
       }
       else if (target == "_search") {
         // Used in WinIE as a way of transiently loading pages in a sidebar.  We
         // mimic that WinIE functionality here and also load the page transiently.
         openWebPanel(gNavigatorBundle.getString("webPanels"), linkNode.href);
         event.preventDefault();
         return false;
       }
       
       // Next two lines the only download sort alteration in this function.  
       // Cancel true means we are handling it by sending the url to saveURL
       var cancel = ds_sortCheck(linkNode);
       if (cancel) return false;
     }
     else
       handleLinkClick(event, linkNode.href, linkNode);
     return true;
   } else {
     // Try simple XLink
     var href;
     linkNode = target;
     while (linkNode) {
       if (linkNode.nodeType == Node.ELEMENT_NODE) {
         href = linkNode.getAttributeNS("http://www.w3.org/1999/xlink", "href");
         break;
       }
       linkNode = linkNode.parentNode;
     }
     if (href) {
       href = makeURLAbsolute(target.baseURI,href);
       handleLinkClick(event, href, null);
       return true;
     }
   }
   if (event.button == 1 &&
       !findParentNode(event.originalTarget, "scrollbar") &&
       gPrefService.getBoolPref("middlemouse.contentLoadURL")) {
     middleMousePaste(event);
   }
   return true;
 }
 
 function ds_sortCheck(linkNode) {
 	//d("insortcheck");
 	var ds_file = linkNode.href.split("/").pop().split(".");
 	if (ds_file.length > 1) {
 		var ds_fileext = ds_file[ds_file.length - 1].toLowerCase();
 		
 		if (ds_fileext != "html" && ds_fileext != "htm" && ds_fileext != "php" && ds_fileext != "shtml"  && ds_fileext != "phtml" && ds_fileext != "xpi") {
 			//d(ds_fileext);
  			const ds_mimeSvc = Components.classes["@mozilla.org/mime;1"].getService(Components.interfaces.nsIMIMEService);
     		try {
     			MIMEInfo = ds_mimeSvc.getFromTypeAndExtension(null, ds_fileext);
     			if(MIMEInfo.preferredAction == 0) {
     				saveURL(linkNode.href, "");
     				//d("mysavedURL");
     				return true;
     			}
     				
 			} catch(e) {
 				//d("error");
 			}
 		}
 		
 	}
 	return false;
 }
 
 function ds_startDownloadSeq() {
 	//d("inseq");
 	var currURL = document.getElementById("urlbar").value;
 	var selStart = document.getElementById("urlbar").selectionStart;
 	var selEnd = document.getElementById("urlbar").selectionEnd;
 	if (selStart == selEnd) {
 		alert("Download Sequential.  Nothing selected - please select a number in the URL");
 		return;
 	}
 	//d(selEnd);
 	window.openDialog("chrome://downsort/content/downloadSeq.xul","showmore", "chrome", currURL, selStart, selEnd);
 }
 
 function ds_doDownloadSeq(url, startSel, endSel, firstNum, lastNum, interval) {
 	var preUrl = url.substring(0,startSel);
 	var postUrl = url.substring(endSel, url.length);
 	var origNum = firstNum;
 	var newNum = firstNum;
 	var currUrl = preUrl + firstNum + postUrl;
 	//d(getReferrer(document).path);
 	
    while (parseInt(newNum, 10) <= parseInt(lastNum, 10)) {
    	
    	saveURL(currUrl, "", "", false, false, getReferrer(document));
    	//d(currUrl);
    	newNum = '' + (parseInt(origNum,10) + parseInt(interval, 10));
 		while (newNum.length < origNum.length)
        	newNum = '0' + newNum;
        origNum = newNum;
        currUrl = preUrl + newNum + postUrl;
    }
 	
 }
 

// Dump a message to Javascript Console
/*function d(msg){
	var acs = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
	acs.logStringMessage(msg);
}*/